#include "vresource.h"
#include "vmalloc.h"

#include <pthread.h>
#include <sys/prctl.h>
#include <time.h>
#include <errno.h>
#include <signal.h>
#include <sys/types.h>
#include <unistd.h>
#include <semaphore.h>


struct mutex__
{
    pthread_mutex_t mtx;
    pthread_mutexattr_t mtx_attr;
};

vMutex vMutexCreate()
{
    struct mutex__ *mutex = NULL;
    int ret = -1;

    mutex = (struct mutex__ *)vCalloc(1,sizeof(struct mutex__));
    if(!mutex)
    {
        printf("[mutex] mutex no memory\n");
        return NULL;
    }

    ret = pthread_mutexattr_init(&(mutex->mtx_attr));
    if(ret != 0)
    {
        printf("[mutex] mutex attr init failed\n");
        vFree(mutex);
        return NULL;
    }
    /* 线程用*/
    pthread_mutexattr_setpshared(&(mutex->mtx_attr),PTHREAD_PROCESS_PRIVATE);
    /*设置健壮性*/
    pthread_mutexattr_setrobust(&(mutex->mtx_attr),PTHREAD_MUTEX_ROBUST);

    ret = pthread_mutex_init(&(mutex->mtx),&(mutex->mtx_attr));
    if(ret != 0)
    {
        printf("[mutex] mutex init failed\n");
        pthread_mutexattr_destroy(&(mutex->mtx_attr));
        vFree(mutex);
        return NULL;
    }

    return (vMutex)mutex;
}

int vMutexDestroy(vMutex mtx)
{
    int ret = -1;
    struct mutex__ *mutex = (struct mutex__ *)mtx;
    if(!mutex)
        return -1;
    ret = pthread_mutexattr_destroy(&mutex->mtx_attr);
    if(ret != 0)
    {
        vFree(mutex);
        return -1;
    }
    ret = pthread_mutex_destroy(&mutex->mtx);
    if(ret != 0)
    {
        vFree(mutex);
        return -1;
    }

    vFree(mtx);
    return 0;
}

int vMutexLock(vMutex mtx)
{
    struct mutex__ *mutex = (struct mutex__ *)mtx;
    if(!mutex)
        return -1;
    int ret = pthread_mutex_lock(&mutex->mtx);
    //printf("ret = %d\n",ret);
    if(ret == EOWNERDEAD)
    {
        /* 恢复该锁的一致性*/
        pthread_mutex_consistent(&mutex->mtx);
        return 0;
    }
    return ret;
}

int vMutexTrylock(vMutex mtx)
{
    struct mutex__ *mutex = (struct mutex__ *)mtx;
    if(!mutex)
        return -1;
    /* 如果锁被占用 返回EBUSY 而不是阻塞*/
    int ret = pthread_mutex_trylock(&mutex->mtx);
    if(ret == EBUSY)
        return -1;
    return ret;
}

int vMutexUnlock(vMutex mtx)
{
    struct mutex__ *mutex = (struct mutex__ *)mtx;
    if(!mutex)
        return -1;
    return pthread_mutex_unlock(&mutex->mtx);
}

struct cond__
{
    pthread_cond_t cnd;
    pthread_condattr_t cnd_attr;
};

vCond vCondCreate()
{
    struct cond__ *cond = (struct cond__ *)vCalloc(1,sizeof(struct cond__));
    if(!cond)
        return NULL;

    pthread_condattr_init(&cond->cnd_attr);
    pthread_condattr_setpshared(&cond->cnd_attr,PTHREAD_PROCESS_PRIVATE);

    pthread_cond_init(&cond->cnd,&cond->cnd_attr);

    return (vCond)cond;
}
int vCondDestroy(vCond cnd)
{
    struct cond__ *cond = (struct cond__ *)cnd;
    if(!cond)
        return -1;

    pthread_condattr_destroy(&cond->cnd_attr);
    pthread_cond_destroy(&cond->cnd);

    vFree(cond);
    return 0;
}
int vCondSignal(vCond cnd)
{
    struct cond__ *cond = (struct cond__ *)cnd;
    if(!cond)
        return -1;
    return pthread_cond_signal(&cond->cnd);
}
int vCondBroadcast(vCond cnd)
{
    struct cond__ *cond = (struct cond__ *)cnd;
    if(!cond)
        return -1;
    return pthread_cond_broadcast(&cond->cnd);
}
int vCondWait(vCond cnd,vMutex mtx)
{
    struct cond__ *cond = (struct cond__ *)cnd;
    struct mutex__ *mutex = (struct mutex__*)mtx;
    if(!cond || !mutex)
        return -1;
    return pthread_cond_wait(&cond->cnd,&mutex->mtx);
}
int vCondWaitTimeout(vCond cnd,vMutex mtx,int ms)
{
    struct cond__ *cond = (struct cond__ *)cnd;
    struct mutex__ *mutex = (struct mutex__*)mtx;
    if(!cond || !mutex)
        return -1;
    struct timespec tv;
    tv.tv_sec = (ms / 1000);
    tv.tv_nsec = (ms % 1000) * 1000;

    return pthread_cond_timedwait(&cond->cnd,&mutex->mtx,&tv);
}


struct rw_lock__
{
    pthread_rwlock_t lck;
    pthread_rwlockattr_t lck_attr;
};

vRwlock vRwlockCreate()
{
    struct rw_lock__ *rwlock = (struct rw_lock__ *)vCalloc(1,sizeof(struct rw_lock__));
    if(!rwlock)
        return NULL;

    pthread_rwlockattr_init(&rwlock->lck_attr);
    pthread_rwlockattr_setpshared(&rwlock->lck_attr,PTHREAD_PROCESS_PRIVATE);

    pthread_rwlock_init(&rwlock->lck,&rwlock->lck_attr);

    return (vRwlock)rwlock;
}

int vRwlockRDlock(vRwlock lock)
{
    struct rw_lock__ *rwlock = (struct rw_lock__ *)lock;
    if(!rwlock)
        return -1;
    return pthread_rwlock_rdlock(&rwlock->lck);
}

int vRwlockWRlock(vRwlock lock)
{
    struct rw_lock__ *rwlock = (struct rw_lock__ *)lock;
    if(!rwlock)
        return -1;
    return pthread_rwlock_wrlock(&rwlock->lck);
}

int vRwlockUnlock(vRwlock lock)
{
    struct rw_lock__ *rwlock = (struct rw_lock__ *)lock;
    if(!rwlock)
        return -1;
    return pthread_rwlock_unlock(&rwlock->lck);
}

int vRwlockDestroy(vRwlock lock)
{
    struct rw_lock__ *rwlock = (struct rw_lock__ *)lock;
    if(!rwlock)
        return -1;

    pthread_rwlockattr_destroy(&rwlock->lck_attr);
    pthread_rwlock_destroy(&rwlock->lck);
    vFree(rwlock);
    return 0;
}

int vRwlockTryRDlock(vRwlock lock)
{
    struct rw_lock__ *rwlock = (struct rw_lock__ *)lock;
    if(!rwlock)
        return -1;
    return pthread_rwlock_tryrdlock(&rwlock->lck);
}

int vRwlockTrywrlock(vRwlock lock)
{
    struct rw_lock__ *rwlock = (struct rw_lock__ *)lock;
    if(!rwlock)
        return -1;
    return pthread_rwlock_trywrlock(&rwlock->lck);
}

struct spin_lock__
{
    pthread_spinlock_t lck;
};

vSpin vSpinCreate()
{
    struct spin_lock__ *spinlock = (struct spin_lock__ *)vCalloc(1,sizeof(struct spin_lock__));
    if(!spinlock)
        return NULL;
    pthread_spin_init(&spinlock->lck,0);

    return (vSpin)spinlock;
}

int vSpinDestroy(vSpin spin)
{
    struct spin_lock__ *spinlock = (struct spin_lock__ *)spin;
    if(!spinlock)
        return -1;
    pthread_spin_destroy(&spinlock->lck);
    vFree(spin);
    return 0;
}

int vSpinLock(vSpin spin)
{
    struct spin_lock__ *spinlock = (struct spin_lock__*)spin;
    if(!spinlock)
        return -1;
    return pthread_spin_lock(&spinlock->lck);
}

int vSpinUnlock(vSpin spin)
{
    struct spin_lock__ *spinlock = (struct spin_lock__*)spin;
    if(!spinlock)
        return -1;
    return pthread_spin_unlock(&spinlock->lck);
}

int vSpinTrylock(vSpin spin)
{
    struct spin_lock__ *spinlock = (struct spin_lock__*)spin;
    if(!spinlock)
        return -1;
    return pthread_spin_trylock(&spinlock->lck);
}

struct sem__
{
    sem_t sm;
};

vSem vSemCreate()
{
    struct sem__ *sem = (struct sem__ *)vCalloc(1,sizeof(struct sem__));
    if(!sem)
        return NULL;
    int ret = sem_init(&sem->sm,0,1);
    if(ret < 0)
    {
        vFree(sem);
        return NULL;
    }

    return (vSem)sem;

}
int vSemDestroy(vSem sem)
{
    struct sem__ *s_sem = (struct sem__ *)sem;
    if(!s_sem)
        return -1;
    int ret = sem_destroy(&s_sem->sm);
    if(ret < 0)
        return -1;
    vFree(s_sem);
    return 0;
}
int vSemPut(vSem sem)
{
    struct sem__ *s_sem = (struct sem__ *)sem;
    if(!s_sem)
        return -1;

    return sem_wait(&s_sem->sm);
}
int vSemPutTimeout(vSem sem,int ms)
{
    struct sem__ *s_sem = (struct sem__ *)sem;
    if(!s_sem)
        return -1;
    struct timespec tv;
    tv.tv_sec = ms / 1000;
    tv.tv_nsec = (ms % 1000) * 1000;

    return sem_timedwait(&s_sem->sm,&tv);
}
int vSemGet(vSem sem)
{
    struct sem__ *s_sem = (struct sem__ *)sem;
    if(!s_sem)
        return -1;

    return sem_post(&s_sem->sm);
}
